using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;

namespace Burst.Compiler.IL.Tests
{
    internal partial class Vectors
    {
        [TestFixture]
        public partial class BinaryOperators
        {
            // Float3
            [TestFixture]
            public class Float3
            {
                [TestCompiler]
                public static float Add()
                {
                    var left = new float3(1.0f);
                    var right = new float3(1.0f, 2.0f, 3.0f);
                    var result = left + right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float AddFloatRight()
                {
                    var left = new float3(1.0f);
                    var right = 2.0f;
                    var result = left + right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float AddFloatLeft()
                {
                    var left = 2.0f;
                    var right = new float3(1.0f);
                    var result = left + right;
                    return ConvertToFloat(result);
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static float AddByArgs(ref float3 left, ref float3 right)
                {
                    var result = left + right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float Sub()
                {
                    var left = new float3(1.0f);
                    var right = new float3(1.0f, 2.0f, 3.0f);
                    var result = left - right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float SubFloatLeft()
                {
                    var left = 2.0f;
                    var right = new float3(1.0f, 2.0f, 3.0f);
                    var result = left - right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float SubFloatRight()
                {
                    var left = new float3(1.0f, 2.0f, 3.0f);
                    var right = 2.0f;
                    var result = left - right;
                    return ConvertToFloat(result);
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static float SubByArgs(ref float3 left, ref float3 right)
                {
                    var result = left - right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float Mul()
                {
                    var left = new float3(2.0f, 1.0f, 3.0f);
                    var right = new float3(1.0f, 2.0f, 3.0f);
                    var result = left * right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float MulFloatLeft()
                {
                    var left = 2.0f;
                    var right = new float3(1.0f, 2.0f, 3.0f);
                    var result = left * right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float MulFloatRight()
                {
                    var left = new float3(1.0f, 2.0f, 3.0f);
                    var right = 2.0f;
                    var result = left * right;
                    return ConvertToFloat(result);
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static float MulByArgs(ref float3 left, ref float3 right)
                {
                    var result = left * right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float Div()
                {
                    var left = new float3(1.0f, 2.0f, 3.0f);
                    var right = new float3(2.0f, 1.0f, 3.0f);
                    var result = left / right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float DivFloatLeft()
                {
                    var left = 15.0f;
                    var right = new float3(2.0f, 1.0f, 3.0f);
                    var result = left / right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float DivFloatRight()
                {
                    var left = new float3(2.0f, 1.0f, 3.0f);
                    var right = 15.0f;
                    var result = left / right;
                    return ConvertToFloat(result);
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static float DivByArgs(ref float3 left, ref float3 right)
                {
                    var result = left / right;
                    return ConvertToFloat(result);
                }

                [TestCompiler]
                public static float Neg()
                {
                    var left = new float3(1.0f, 2.0f, 3.0f);
                    return ConvertToFloat((-left));
                }

                [TestCompiler]
                public static float Positive()
                {
                    var left = new float3(1.0f, 2.0f, 3.0f);
                    return ConvertToFloat((+left));
                }

                // Comparisons
                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int Equality(float a, float b)
                {
                    return ConvertToInt((new float3(a) == new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int EqualityFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a == b));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int Inequality(float a, float b)
                {
                    return ConvertToInt((new float3(a) != new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int InequalityFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a != b));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int GreaterThan(float a, float b)
                {
                    return ConvertToInt((new float3(a) > new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int GreaterThanFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a > b));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int GreaterThanOrEqual(float a, float b)
                {
                    return ConvertToInt((new float3(a) >= new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int GreaterThanOrEqualFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a >= b));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int LessThan(float a, float b)
                {
                    return ConvertToInt((new float3(a) < new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int LessThanFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a < b));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int LessThanOrEqual(float a, float b)
                {
                    return ConvertToInt((new float3(a) <= new float3(b)));
                }

                [TestCompiler(DataRange.Standard, DataRange.Standard)]
                public static int LessThanOrEqualFloat3(ref float3 a, ref float3 b)
                {
                    return ConvertToInt((a <= b));
                }

                [TestCompiler(DataRange.Standard)]
                public static float ImplicitFloat(float a)
                {
                    // Let float -> float3 implicit conversion
                    return ConvertToFloat((float3)a);
                }

                [TestCompiler(DataRange.Standard)]
                public static float ImplicitInt4(ref int4 a)
                {
                    // Let int4 -> float3 implicit conversion
                    return ConvertToFloat(a);
                }
           }
        }
    }
}